﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;

namespace PHPTibia
{
    public enum IsometricGridTileType
    {
        Colored,
        Textured
    }
    public struct IsometricGridTile
    {
        public IsometricGridTileType Type;
        public Color Color, ShadowColor;
        public Image Texture, Overlay;
        public bool CastShadow, IsReflectible;
        public short Level, Reflectivity, ReflectX, ReflectY;
    }
    public class IsometricGridRenderer
    {
        IsometricGridTile[,] _tiles;
        public IsometricGridTile[,] Tiles
        {
            get
            {
                return _tiles;
            }
        }
        public Image Output;
        int TileSize = 64;
        public IsometricGridRenderer(Image output)
        {
            this.Output = output;
            ComputeTiles(output.Width, output.Height);
        }
        public IsometricGridRenderer(int TileSize, Image output)
        {
            this.Output = output;
            this.TileSize = TileSize;
            ComputeTiles(output.Width, output.Height);
        }
        public IsometricGridRenderer(int Width, int Height)
        {
            this.Output = new Bitmap(Width, Height);
            ComputeTiles(Width, Height);
        }
        public IsometricGridRenderer(int TileSize, int Width, int Height)
        {
            this.TileSize = TileSize;
            Output = new Bitmap(Width, Height);
            ComputeTiles(Width, Height);
        }
        public void SetTile(int x, int y, IsometricGridTile tile)
        {
            _tiles.SetValue(tile, x, y);
            Draw(x, y, tile);
        }
        public void SetTileNotDraw(int x, int y, IsometricGridTile tile)
        {
            _tiles.SetValue(tile, x, y);
        }
        public int GetTileSize()
        {
            return TileSize;
        }
        public Size GetTiles()
        {
            return new Size(Output.Width / TileSize, Output.Height / TileSize);
        }
        public void Draw()
        {
            IsometricGridTile tile;
            for (int x = 0; x < Output.Width / TileSize; x++)
            {
                for (int y = 0; y < Output.Height / TileSize; y++)
                {
                    tile = _tiles[x, y];
                    Draw(x, y, tile);
                }
            }
        }
        public void Draw(int x, int y, IsometricGridTile tile)
        {
            using (Graphics g = Graphics.FromImage(Output))
            {
                Rectangle drawPosition = new Rectangle(x * TileSize, y * TileSize, TileSize, TileSize);
                g.DrawImage(DrawTileBase(tile), drawPosition);
                if (tile.Overlay != null) g.DrawImage(tile.Overlay, drawPosition);
            }
        }
        public Point AbsoluteToTile(Point loc)
        {
            return new Point(loc.X / TileSize, loc.Y / TileSize);
        }
        public Point TileToAbsolute(Point loc)
        {
            return new Point(loc.X * TileSize, loc.Y * TileSize);
        }
        public void Clear(IsometricGridTile tile)
        {
            for (int x = 0; x < GetTiles().Width; x++)
            {
                for (int y = 0; y < GetTiles().Height; y++)
                {
                    SetTileNotDraw(x, y, tile);
                }
            }
            Draw();
        }
        public Image DrawTileBase(IsometricGridTile tile)
        {
            Image ret = new Bitmap(TileSize, TileSize);
            Rectangle drawPosition = new Rectangle(0, 0, TileSize, TileSize);
            using (Graphics g = Graphics.FromImage(ret))
            {
                bool drawTexture = false;
                if (tile.Type == IsometricGridTileType.Textured && tile.Texture != null) drawTexture = true;
                switch (drawTexture)
                {
                    case true:
                        g.DrawImage(tile.Texture, drawPosition);
                        break;
                    case false:
                        g.FillRectangle(new SolidBrush(tile.Color), drawPosition);
                        break;
                }
            }
            return ret;
        }
        void ComputeTiles(int width, int height)
        {
            _tiles = new IsometricGridTile[width / TileSize, height / TileSize];
            _tiles.Initialize();
        }
    }
    class ImageFX
    {
        public static Image DoComposite(Image Source, Image Overlay)
        {
            Image img = (Image)Source.Clone();
            using (Graphics g = Graphics.FromImage(img))
            {
                g.DrawImage(Overlay, new Rectangle(0, 0, img.Width, img.Height));
            }
            return img;
        }
        public static Image DoShadow(Image Source, bool Forward)
        {
            LinearGradientBrush lgb;
            Image shadow = (Image)Source.Clone();
            Rectangle rect = new Rectangle(0,0, Source.Width, Source.Height);
            if (Forward) lgb = new LinearGradientBrush(rect, Color.Black, Color.Transparent, LinearGradientMode.Vertical);
            else lgb = new LinearGradientBrush(rect, Color.Transparent, Color.Black, LinearGradientMode.Vertical);
            using (Graphics g = Graphics.FromImage(shadow))
            {
                g.FillRectangle(lgb, rect);
            }
            return shadow;
        }
    }
}
